local ROT = require((...):gsub(('.[^./\\]*'):rep(1) .. '$', ''))
local TTYDisplay = ROT.Class:extend("TTYDisplay")

function TTYDisplay:init(width, height)
    self.width, self.height = width, height
    self:clear()
end

function TTYDisplay:getWidth()
    return self.width
end

function TTYDisplay:getHeight()
    return self.height
end

function TTYDisplay:draw()
    local value
    io.stdout:write('\27[0;0H')
    for y = 1, self.height do
        for x = 1, self.width do
            local prev = value
            value = self.lines[y][x]
            if prev and not value then
                io.stdout:write('\27[0m')
            end
            io.stdout:write(value or ' ')
        end
        if y < self.height then io.stdout:write('\n') end
    end
end

function TTYDisplay:clear()
    self.lines = {}
    for y = 1, self.height do
        self.lines[y] = {}
    end
end

local function clamp (c)
    return math.min(math.max(0, c), 255)
end

function TTYDisplay:write(text, x, y, fg, bg, single)
    local fgstring = (fg and ('\27[38;2;%i;%i;%im')
        :format(clamp(fg[1]), clamp(fg[2]), clamp(fg[3])) or '\27[38;2;240;240;240m')
    local bgstring = (bg and ('\27[48;2;%i;%i;%im')
        :format(clamp(bg[1]), clamp(bg[2]), clamp(bg[3])) or '\27[48;2;0;0;0m')
    text = tostring(text)
    self.lines[y] = self.lines[y] or {}
    if single then
        self.lines[y][x] = fgstring .. bgstring .. text
    else
        self.lines[y][x] = fgstring .. bgstring .. text:sub(1, 1)
        for i = 2, #text do
            x = x + 1
            self.lines[y][x] = text:sub(i, i)
        end
    end
end

return TTYDisplay

